package com.poisson;

import javax.swing.*;
import java.awt.*;

/**
 * 画坐标Service
 */
public class PaintCoordinateService {

    public static void paintCoordinate(Double[] xNumberArray, Double[] yNumberArray) {
        StringBuffer logBuffer = new StringBuffer("paintCoordinate: \n");
        for (int i = 0; i < xNumberArray.length; i++) {
            logBuffer.append("(").append(xNumberArray[i]).append(",").append(yNumberArray[i]).append(") - ").append(i).append("\n");
        }
        System.err.println(logBuffer);

        JFrame frame = new JFrame("绘制");
        // Setting the width and height of frame
        frame.setSize(1400, 1000);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new MyPanel(xNumberArray, yNumberArray));
        frame.setVisible(true);
    }


    private static class MyPanel extends JPanel {

        private static final int X_START = 200;

        private static final int X_END = 1050;

        private static final int ARROW_LENGTH = 20;

        private static final int Y_START = 900;

        private static final int Y_END = 50;

        private static final int X_LENGTH = X_END - X_START;

        private static final int Y_LENGTH = Y_START - Y_END;

        private static final int NUMBER_LENGTH = 10;

        private static final double X_SCALE_MIN_UNIT = 0.0000001;

        private static final int X_SCALE_INCREASE_FACTOR_5 = 5;

        private static final int X_SCALE_INCREASE_FACTOR_2 = 2;

        private static final int X_SCALE_NUM = 5;

        private static final int X_SCALE_UNIT_LENGTH = 10;

        private static final int X_SCALE_DIGITAL_HEIGHT = 15;

        private static final double Y_SCALE_MIN_UNIT = 0.0000001;

        private static final int Y_SCALE_INCREASE_FACTOR_5 = 5;

        private static final int Y_SCALE_INCREASE_FACTOR_2 = 2;

        private static final int Y_SCALE_NUM = 5;

        private static final int Y_SCALE_UNIT_LENGTH = 10;

        private static final int Y_SCALE_DIGITAL_HEIGHT = 40;

        private Double[] xNumberArray;

        private Double[] yNumberArray;

        private Double xMaxNumber;
        private Double yMaxNumber;

        public MyPanel(Double[] xNumberArray, Double[] yNumberArray) {
            this.xNumberArray = xNumberArray;
            this.yNumberArray = yNumberArray;
            for (int i = 0; i < xNumberArray.length; i++) {
                if (xMaxNumber == null || xMaxNumber < xNumberArray[i]) {
                    xMaxNumber = xNumberArray[i];
                }
            }

            for (int i = 0; i < yNumberArray.length; i++) {
                if (yMaxNumber == null || yMaxNumber < yNumberArray[i]) {
                    yMaxNumber = yNumberArray[i];
                }
            }
        }

        @Override
        public void paintComponent(Graphics g) {

            super.paintComponent(g);

            Graphics2D g2D = (Graphics2D) g;

            Color c = new Color(200, 70, 0);

            g2D.setColor(c);

            /**
             * 画X轴
             */
            g2D.drawLine(X_START, Y_START, X_END, Y_START);

            /**
             * 画Y轴
             */
            g2D.drawLine(X_START, Y_START, X_START, Y_END);

            /**
             * 画X轴上箭头
             */
            g2D.drawLine(X_END, Y_START, X_END - ARROW_LENGTH, Y_START - ARROW_LENGTH);

            /**
             * 画X轴下箭头
             */
            g2D.drawLine(X_END, Y_START, X_END - ARROW_LENGTH, Y_START + ARROW_LENGTH);

            /**
             * 画Y轴左箭头
             */
            g2D.drawLine(X_START, Y_END, X_START - ARROW_LENGTH, Y_END + ARROW_LENGTH);

            /**
             * 画Y轴右箭头
             */
            g2D.drawLine(X_START, Y_END, X_START + ARROW_LENGTH, Y_END + ARROW_LENGTH);

            /**
             * 画原点
             */
            g2D.drawString( "0", X_START - NUMBER_LENGTH, Y_START + NUMBER_LENGTH);

            double xUnit = Double.valueOf(X_LENGTH) / xMaxNumber;

            double yUnit = Double.valueOf(Y_LENGTH) / yMaxNumber;

            System.err.printf("paintComponent xUnit=%s,yUnit=%s,xMaxNumber=%s,yMaxNumber=%s \n", xUnit, yUnit, xMaxNumber, yMaxNumber);

            /**
             * 把相邻的两个点连线
             */
            for (int i = 0; i < xNumberArray.length - 1; i++) {
                System.err.printf("paintComponent g2D.drawLine(%s,%s,%s,%s) \n", X_START + (int) (xNumberArray[i] * xUnit), Y_START - (int) (yNumberArray[i] * yUnit), X_START + (int) (xNumberArray[i + 1] * xUnit), Y_START - (int) (yNumberArray[i + 1] * yUnit));
                g2D.drawLine(X_START + (int) (xNumberArray[i] * xUnit), Y_START - (int) (yNumberArray[i] * yUnit),
                        X_START + (int) (xNumberArray[i + 1] * xUnit), Y_START - (int) (yNumberArray[i + 1] * yUnit));
            }

            /**
             * 计算合适的X轴刻度
             */
            Double xScaleUnit = X_SCALE_MIN_UNIT;
            int currentXScaleIncreaseFactor = X_SCALE_INCREASE_FACTOR_5;
            while (true) {
                if (xMaxNumber / X_SCALE_NUM < xScaleUnit) {
                    break;
                }
                xScaleUnit = xScaleUnit * currentXScaleIncreaseFactor;
                currentXScaleIncreaseFactor = currentXScaleIncreaseFactor == X_SCALE_INCREASE_FACTOR_5 ? X_SCALE_INCREASE_FACTOR_2 : X_SCALE_INCREASE_FACTOR_5;
            }
            currentXScaleIncreaseFactor = currentXScaleIncreaseFactor == X_SCALE_INCREASE_FACTOR_5 ? X_SCALE_INCREASE_FACTOR_2 : X_SCALE_INCREASE_FACTOR_5;
            xScaleUnit = xScaleUnit / currentXScaleIncreaseFactor;
            System.err.printf("paintComponent xScaleUnit=%s \n", xScaleUnit);

            /**
             * 计算合适的Y轴刻度
             */
            Double yScaleUnit = Y_SCALE_MIN_UNIT;
            int currentYScaleIncreaseFactor = Y_SCALE_INCREASE_FACTOR_5;
            while (true) {
                if (yMaxNumber / Y_SCALE_NUM < yScaleUnit) {
                    break;
                }
                yScaleUnit = yScaleUnit * currentYScaleIncreaseFactor;
                currentYScaleIncreaseFactor = currentYScaleIncreaseFactor == Y_SCALE_INCREASE_FACTOR_5 ? Y_SCALE_INCREASE_FACTOR_2 : Y_SCALE_INCREASE_FACTOR_5;
            }
            currentXScaleIncreaseFactor = currentXScaleIncreaseFactor == X_SCALE_INCREASE_FACTOR_5 ? X_SCALE_INCREASE_FACTOR_2 : X_SCALE_INCREASE_FACTOR_5;
            yScaleUnit = yScaleUnit / currentXScaleIncreaseFactor;
            System.err.printf("paintComponent yScaleUnit=%s \n", yScaleUnit);

            /**
             * 画X轴的刻度
             */
            Double xScaleUnitLength = (X_LENGTH / xMaxNumber) * xScaleUnit;
            int xTimes = 0;
            while (true) {
                if (xScaleUnit * xTimes > xMaxNumber) {
                    break;
                }
                if (xTimes == 0) {
                    xTimes++;
                    continue;

                }
                String xScaleText = prettifyScaleText(String.valueOf((xScaleUnit >= 1 ? xScaleUnit.intValue() : xScaleUnit) * xTimes));
                System.err.printf("paintComponent paint xScale=%s \n", xScaleText);
                g2D.drawString(xScaleText, X_START + xScaleUnitLength.intValue() * xTimes, Y_START + X_SCALE_DIGITAL_HEIGHT);
                g2D.drawLine(X_START + xScaleUnitLength.intValue() * xTimes, Y_START, X_START + xScaleUnitLength.intValue() * xTimes, Y_START - X_SCALE_UNIT_LENGTH);
                xTimes++;
            }

            /**
             * 画Y轴的刻度
             */
            Double yScaleUnitLength = (Y_LENGTH / yMaxNumber) * yScaleUnit;
            int yTimes = 0;
            while (true) {
                if (yScaleUnit * yTimes > yMaxNumber) {
                    break;
                }
                if (yTimes == 0) {
                    yTimes++;
                    continue;
                }
                String yScaleText = prettifyScaleText(String.valueOf((yScaleUnit >= 1 ? yScaleUnit.intValue() : yScaleUnit) * yTimes));

                System.err.printf("paintComponent paint yScale=%s \n", yScaleText);
                g2D.drawString(yScaleText, X_START - Y_SCALE_DIGITAL_HEIGHT, Y_START - yScaleUnitLength.intValue() * yTimes);
                g2D.drawLine(X_START, Y_START - yScaleUnitLength.intValue() * yTimes, X_START + Y_SCALE_UNIT_LENGTH, Y_START - yScaleUnitLength.intValue() * yTimes);
                yTimes++;
            }
        }
    }

    /**
     * 美化刻度值
     * 去掉尾部小数点后连续的0
     * @param scaleText
     * @return
     */
    private static String prettifyScaleText(String scaleText) {
        int dotIndex = scaleText.indexOf(".");
        if (dotIndex < 0) {
            return scaleText;
        }
        char[] cs = scaleText.toCharArray();
        int lastZeroIndex = -1;
        for (int i = cs.length - 1; i >=0; i--) {
            if (cs[i] != '0') {
                break;
            }
            lastZeroIndex = i;
        }
        if (lastZeroIndex == -1) {
            return scaleText;
        }

        return scaleText.substring(0, lastZeroIndex - dotIndex == 1 ? lastZeroIndex + 1 : lastZeroIndex);
    }

    public static void main(String[] args) {
        System.err.println(prettifyScaleText("1000000000.000000"));
        System.err.println(prettifyScaleText("100.0"));
        System.err.println(prettifyScaleText("110.0"));
        System.err.println(prettifyScaleText("103.0"));
        System.err.println(prettifyScaleText("183.0"));
        System.err.println(prettifyScaleText("100.01"));
        System.err.println(prettifyScaleText("110.02"));
        System.err.println(prettifyScaleText("103.03"));
        System.err.println(prettifyScaleText("183.04"));
    }
}